#pragma once
#include <iostream>
#include <string>

#include <jsoncpp/json/json.h>
using namespace std;

//"len"\r\n"{json_str}"\r\n"---报文

//无论客户端发送Request请求或者服务端对该请求进行Response,都需要将Request/Response添加协议报头
//从而确保报文的完整性,但是当服务端收到Request/客户端收到Response均需要对报文的完整性进行判定

//添加协议报头,向外部返回添加报头后的字符串
const std::string SEP="\r\n";

std::string Encode(const std::string& json_str)
{
    int json_str_len=json_str.size();
    std::string proto_str=to_string(json_str_len);
    proto_str+=SEP;
    proto_str+=json_str;
    proto_str+=SEP;
    return proto_str;
}

//检测报文的完整性,若至少存在一条完整报文,将此报文切割出json串,返回json串,否则返回空串
//"len"\r\n"{json_str}"\r\n"
std::string Decode(std::string& message)
{
    size_t pos=message.find(SEP);
    if(pos==std::string::npos) return std::string();
    std::string lenstr=message.substr(0,pos);
    if(lenstr.empty()) return std::string();
    int len=std::stoi(lenstr);

    //判定是否至少存在一条完整的报文
    int total=len+lenstr.size()+2*SEP.size();
    if(message.size()<total)
    {
        return std::string();
    }
    std::string json_str=message.substr(pos+SEP.size(),len);
    //删除众多报文中的第一条协议报文
    message.erase(0,total);
    return json_str;
}



class Request
{
public:
    Request()
    {}
    Request(int x,int y,char oper):_x(x),_y(y),_oper(oper)
    {}

    //客户端将发送的数据需要进行序列化将结构化数据转换为字符串发送到服务端
    void Serialize(std::string* out)
    {
        Json::Value root;
        root["x"]=_x;
        root["y"]=_y;
        root["oper"]=_oper;
        Json::FastWriter writer;
        *out=writer.write(root);
    }

    //服务端接收到客户端的数据,需要将字符串转换为结构化数据
    bool Deserialize(const std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool res=reader.parse(in,root);
        if(!res)
            return false;
        
        _x=root["x"].asInt();
        _y=root["y"].asInt();
        _oper=root["oper"].asInt();
        return true;
    }

    ~Request()
    {}
    
public:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
    {}
    Response(int result,int code):_result(result),_code(code)
    {}

    //服务端将数据处理后的结果(结构化数据)需要转换为字符串,采用输出型参数方便外部发送json字符串
    void Serialize(std::string* out)
    {
        Json::Value root;
        root["result"]=_result;
        root["code"]=_code;
        Json::FastWriter writer;
        *out=writer.write(root);
    }

    //客户端接收服务端数据的处理结果需要将字符串转换为结构化数据
    bool Deserialize(const std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool res=reader.parse(in,root);
        if(!res)
            return false;
        _result=root["result"].asInt();
        _code=root["code"].asInt();
        return true;
    }

    ~Response()
    {}
public:
    int _result;
    int _code;//0:结果可信 1:除0错误 2:模0错误 3:非法操作
};